package com.leen.controller;

import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.leen.common.exception.AccountLockedException;
import com.leen.common.exception.AccountNotFoundException;
import com.leen.common.exception.PasswordIncorrectException;
import com.leen.common.vo.ResultEnum;
import com.leen.common.vo.ResultVO;
import com.leen.exception.AccessDeniedException;
import com.leen.exception.TokenEmptyException;
import com.leen.exception.TokenInvalidException;
import io.jsonwebtoken.ExpiredJwtException;

import io.jsonwebtoken.MalformedJwtException;
import lombok.extern.log4j.Log4j2;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLIntegrityConstraintViolationException;

/**
 * springmvc全局异常处理
 * @author wy
 */
@Log4j2
@Order(value = Ordered.HIGHEST_PRECEDENCE)
@RestControllerAdvice
public class LeenExceptionControllerHandler {

    /**
     * hibernate验证框架异常处理操作
     */
    @ExceptionHandler(value = {BindException.class})
    public ResultVO hibernateException(BindException bindException){
        log.error(bindException.getMessage());
        String msg=bindException.getFieldErrors().get(0).getDefaultMessage();
        ResultVO resultVO= ResultVO.failed(ResultEnum.FAILED);
        resultVO.setMessage(msg);
        return resultVO;
    }

    /**
     * hibernate验证框架异常处理操作(post提交  + @RequestBody +@Valid报的异常)
     */
    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    public ResultVO methodArgumentNotValidException(MethodArgumentNotValidException bindException){
        log.error(bindException.getMessage());
        String msg=bindException.getBindingResult().getAllErrors().get(0).getDefaultMessage();
        ResultVO resultVO= ResultVO.failed(ResultEnum.FAILED);
        resultVO.setMessage(msg);
        return resultVO;
    }

    //.SQLIntegrityConstraintViolationException
    /**
     * 数据库唯一约束异常
     */
    @ExceptionHandler(value = {SQLIntegrityConstraintViolationException.class})
    public ResultVO sQLIntegrityConstraintViolationException(SQLIntegrityConstraintViolationException e){
        log.error(e.getMessage());
        ResultVO resultVO= ResultVO.failed(ResultEnum.FAILED);
        resultVO.setMessage("数据库值已存在,不允许重复");
        return resultVO;
    }


    /**
     * 令牌是被恶意更改了
     * @return
     */
    @ExceptionHandler(value = {MismatchedInputException.class})
    public ResultVO tokenMismatchedInputException(MismatchedInputException e){
        log.error(e.getMessage());
        ResultVO resultVO= ResultVO.failed(ResultEnum.TOKEN_TAMPERING);
        return resultVO;
    }






    /**
     * 没有令牌
     * @param e
     * @return
     */
    @ExceptionHandler(value = {TokenEmptyException.class})
    public ResultVO tokenEmptyException(TokenEmptyException  e){
        log.error(e.getMessage());
        ResultVO resultVO= ResultVO.failed(ResultEnum.TOKEN_EMPTY);
        return resultVO;
    }

    /**
     * 令牌有问题
     * @param e
     * @return
     */
    @ExceptionHandler(value = {TokenInvalidException.class})
    public ResultVO tokenInvalidException(TokenInvalidException  e){
        log.error(e.getMessage());
        ResultVO resultVO= ResultVO.failed(ResultEnum.TOKEN_EMPTY);
        return resultVO;
    }

    /**
     * 令牌被篡改
     * @param e
     * @return
     */
    @ExceptionHandler(value = {MalformedJwtException.class})
    public ResultVO malformedJwtException(MalformedJwtException  e){
        log.error(e.getMessage());
        ResultVO resultVO= ResultVO.failed(ResultEnum.TOKEN_TAMPERING);
        return resultVO;
    }


    /**
     * 令牌过期
     * @param e
     * @return
     */
    @ExceptionHandler(value = {ExpiredJwtException.class})
    public ResultVO expiredJwtException(ExpiredJwtException  e){
        log.error(e.getMessage());
        ResultVO resultVO= ResultVO.failed(ResultEnum.TOKEN_EXPIRED);
        return resultVO;
    }


    /**
     * 找不到用户
     * @param e
     * @return
     */
    @ExceptionHandler(value = {AccountNotFoundException.class})
    public ResultVO notFoundTeacherException(AccountNotFoundException e)
    {
        log.error(e.getMessage());
        return ResultVO.failed(ResultEnum.USER_LOGIN_FILE);
    }


    /**
     * 密码无效（错误）
     * @param e
     * @return
     */
    @ExceptionHandler(value = {PasswordIncorrectException.class})
    public ResultVO invalidPasswordException(PasswordIncorrectException e)
    {
        log.error(e.getMessage());
        return ResultVO.failed(ResultEnum.USER_LOGIN_FILE);
    }

    /**
     * 账户被禁用
     * @param e
     * @return
     */
    @ExceptionHandler(value = {AccountLockedException.class})
    public ResultVO accountLockedException(AccountLockedException e)
    {
        log.error(e.getMessage());
        return ResultVO.failed(ResultEnum.USER_FROZEN);
    }

    /**
     * 未授权访问异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = {AccessDeniedException.class})
    public ResultVO accessDeniedException(AccessDeniedException e)
    {
        log.warn(e.getMessage());
        return ResultVO.failed(ResultEnum.Forbidden);
    }


}
